#include "Sintatico.h"

Sintatico::~Sintatico()
{
}

Sintatico::Sintatico()
{
    this->mNivelLexico = 0;
    this->mIsExpressao = false;
}

bool Sintatico::analiza(Arvore *arvore, Hash *tabelaHash)
{
    this->mTabelaHash = tabelaHash;
    return programa(arvore);
}

void Sintatico::setListaTokens(std::list<TToken *> pLista)
{
    this->tokens.setListaTokens(pLista);
}

void Sintatico::incrementaNivel()
{
    this->mNivelLexico++;    
}

void Sintatico::decrementaNivel()
{
    this->mNivelLexico--;
}

int Sintatico::getNivel() const
{
    return this->mNivelLexico;
}

bool Sintatico::isTipo()
{
    TToken temp;
    temp = tokens.getTokenAtual();
    
    if ( temp.isTipo() ) return true;
    else return false;
}

bool Sintatico::identificador()
{
    TToken temp;
    temp = tokens.getTokenAtual();

    if ( temp.isIdentificador() ) return true;

    else return false;
    
} //bool Sintatico::identificador()

bool Sintatico::numero()
{
    TToken temp;
    temp = tokens.getTokenAtual();

    if ( temp.isNumero() )
    {
        if (this->mIsExpressao) this->mListaExpressao->push_back(temp.token);
        return true;
    }
    else return false;
}

bool Sintatico::fator()
{
    TToken temp = tokens.getTokenAtual();
    
    if ( tokens.getTokenAtual() == "(" )
    {
        this->mListaExpressao->push_back("(");

        tokens.avancaPonteiro();
        if ( expressao() )
        {
            tokens.avancaPonteiro();
            if ( tokens.getTokenAtual() == ")" )
            {
                this->mListaExpressao->push_back(")");
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    else if ( tokens.getTokenAtual() == "not" )
    {
        this->mListaExpressao->push_back("not");

        tokens.avancaPonteiro();
        if ( fator() ) return true;
        else return false;
    }
    else if ( numero() )
    {
        return true;
    }
    else if ( tokens.getTokenAtual() == "true" )
    {
        this->mListaExpressao->push_back("true");
        return true;
    }
    else if ( tokens.getTokenAtual() == "false" )
    {
        this->mListaExpressao->push_back("false");
        return true;
    }
    else if ( identificador() )
    {
        //como existem duas opcoes para identificador, usa um "look ahead" para ver
        // o proximo simbolo
        this->mListaExpressao->push_back(temp.token);

        if ( tokens.getProxToken() == "(" )
        {
            this->mListaExpressao->push_back("(");
            tokens.avancaPonteiro();
            tokens.avancaPonteiro();

            if ( expressao() )
            {
                tokens.avancaPonteiro();
                if ( tokens.getTokenAtual() == ")" )
                {
                    this->mListaExpressao->push_back(")");
                    return true;
                }
                else if ( tokens.getTokenAtual() == "," )
                {
                    bool continuar = true;
                    this->mListaExpressao->push_back(",");
                    tokens.avancaPonteiro();

                    while (continuar)
                    {
                        if ( expressao() )
                        {
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ")" )
                            {
                                this->mListaExpressao->push_back(")");
                                return true;
                            }
                            else if ( tokens.getTokenAtual() == "," )
                            {
                                this->mListaExpressao->push_back(",");
                                tokens.avancaPonteiro();
                            }
                            else return false;
                        }
                        else return false;
                    }//while (continuar)
                }//else if ( tokens.getProxToken() == "," )
                else return false;
                
            }//if ( expressao() )
            else return false;
        }
        else
        {
            return true;
        }
    }

    else return false;
    
    return false;
}

bool Sintatico::termo()
{
    TToken temp;
    temp = tokens.getTokenAtual();
    
    bool continuar = true;
    
    while ( continuar )
    {
        if ( fator() )
        {
            tokens.avancaPonteiro();
            temp = tokens.getTokenAtual();

            if ( tokens.getTokenAtual() == "*" )
            {
                this->mListaExpressao->push_back("*");
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "div" )
            {
                this->mListaExpressao->push_back("div");
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "and" )
            {
                this->mListaExpressao->push_back("and");
                tokens.avancaPonteiro();
            }
            else
            {
                tokens.retrocedePonteiro();
                return true;
            }
        } //if ( fator() )
        else
        {
            return false;
        } 
    }//while ( continuar )
    
}

bool Sintatico::expressao()
{
    if ( expressaoSimples() )
    {
        tokens.avancaPonteiro();

        if ( tokens.getTokenAtual() == "=" )
        {
            this->mListaExpressao->push_back("=");
            tokens.avancaPonteiro();
        }
        else if ( tokens.getTokenAtual() == "<>" )
        {
            this->mListaExpressao->push_back("<>");
            tokens.avancaPonteiro();
        }
        else if ( tokens.getTokenAtual() == "<" )
        {
            this->mListaExpressao->push_back("<");
            tokens.avancaPonteiro();
        }
        else if ( tokens.getTokenAtual() == "<=" )
        {
            this->mListaExpressao->push_back("<=");
            tokens.avancaPonteiro();
        }
        else if ( tokens.getTokenAtual() == ">=" )
        {
            this->mListaExpressao->push_back(">=");
            tokens.avancaPonteiro();
        }
        else if ( tokens.getTokenAtual() == ">" )
        {
            this->mListaExpressao->push_back(">");
            tokens.avancaPonteiro();
        }
        else
        {
            tokens.retrocedePonteiro();
            return true;
        }
        
        if ( expressaoSimples() )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
    
}//fim expressao()

bool Sintatico::expressaoSimples()
{
    TToken temp;
    temp = tokens.getTokenAtual();
    
    bool continuar = true;
    
    if ( tokens.getTokenAtual() == "+" )
    {
        this->mListaExpressao->push_back("+");
        tokens.avancaPonteiro();
    }
    else if ( tokens.getTokenAtual() == "-" )
    {
        this->mListaExpressao->push_back("-");
        tokens.avancaPonteiro();
    }
    
    while (continuar)
    {
        if ( termo() )
        {
            tokens.avancaPonteiro();
            
            if ( tokens.getTokenAtual() == "+" )
            {
                this->mListaExpressao->push_back("+");
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "-" )
            {
                this->mListaExpressao->push_back("-");
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "or" )
            {
                this->mListaExpressao->push_back("or");
                tokens.avancaPonteiro();
            }
            else
            {
                tokens.retrocedePonteiro();
                return true;
            }
        }
        else
        {
            cout << tokens.getTokenAtual().token << "- não é um termo\n";
            return false;
        }
    }
}// fim expressaoSimples()

bool Sintatico::comandoSemRotulo(NoArvore *parent)
{
    if ( tokens.getTokenAtual() == "write" || tokens.getTokenAtual() == "writeln")
    {
        std::string rotulo;
        
        rotulo = (tokens.getTokenAtual() == "write" ? "write" : "writeln");

        NoArvore *noExpressao = parent->inserirFilho(rotulo.c_str());

        tokens.avancaPonteiro();
        
        if (tokens.getTokenAtual() == "(" )
        {
            tokens.avancaPonteiro();

            this->mIsExpressao = true;
            this->mListaExpressao = new std::list<std::string>;

            if ( expressao() )
            {
                noExpressao->inserirFilho(this->mListaExpressao);
                this->mIsExpressao = false;

                tokens.avancaPonteiro();

                if ( tokens.getTokenAtual() == ")" )
                {
                    return true;
                }
                else if ( tokens.getTokenAtual() == "," )
                {
                    bool continuar = true;
                    tokens.avancaPonteiro();

                    while (continuar)
                    {
                        this->mIsExpressao = true;
                        this->mListaExpressao = new std::list<std::string>;

                        if ( expressao() )
                        {
                            this->mIsExpressao = false;
                            noExpressao->inserirFilho(this->mListaExpressao);
                            //showLista();
                            tokens.avancaPonteiro();

                            if ( tokens.getTokenAtual() == ")" )
                            {
                                this->mIsExpressao = false;
                                return true;
                            }
                            else if ( tokens.getTokenAtual() == "," )
                            {
                                tokens.avancaPonteiro();
                            }
                            else return false;
                        }
                        else
                        {
                            this->mIsExpressao = false;
                            return false;
                        }
                    }//while (continuar)
                }
            }
            else return false;
        }
        else return false;
    }
    else if ( tokens.getTokenAtual() == "read" )
    {
        NoArvore *noExpressao = parent->inserirFilho("read");

        tokens.avancaPonteiro();
        
        if (tokens.getTokenAtual() == "(" )
        {
            tokens.avancaPonteiro();

            if ( identificador() )
            {
                noExpressao->inserirFilho(tokens.getTokenAtual().token);
                tokens.avancaPonteiro();

                if ( tokens.getTokenAtual() == ")" )
                {
                    return true;
                }
                else if ( tokens.getTokenAtual() == "," )
                {
                    bool continuar = true;
                    tokens.avancaPonteiro();

                    while (continuar)
                    {
                        if ( identificador() )
                        {
                            noExpressao->inserirFilho(tokens.getTokenAtual().token);
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ")" )
                            {
                                return true;
                            }
                            else if ( tokens.getTokenAtual() == "," )
                            {
                                tokens.avancaPonteiro();
                            }
                            else return false;
                        }
                        else return false;
                    }//while (continuar)
                }
            }
            else return false;
        }
        else return false;
    }
    else if ( tokens.getTokenAtual() == "begin" )
    {
        tokens.avancaPonteiro();
        bool continuar = true;

        while (continuar)
        {
            if ( comando(parent) )
            {
                tokens.avancaPonteiro();

                if ( tokens.getTokenAtual() == "end" )
                {
                    return true;
                }
                if ( tokens.getTokenAtual() == ";" )
                {
                    tokens.avancaPonteiro();
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
    else if ( tokens.getTokenAtual() == "if" )
    {
        NoArvore *noExpressao = parent->inserirFilho("if");
        NoArvore *noCondition = noExpressao->inserirFilho("[condiction]");

        tokens.avancaPonteiro();

        this->mIsExpressao = true;
        this->mListaExpressao = new std::list<std::string>;
        
        if ( expressao() )
        {
            this->mIsExpressao = false;
            noCondition->inserirFilho(this->mListaExpressao);
            //showLista();

            tokens.avancaPonteiro();
            if ( tokens.getTokenAtual() == "then" )
            {
                NoArvore *filho = noExpressao->inserirFilho("[then]");
                
                tokens.avancaPonteiro();
                
                if ( comandoSemRotulo(filho) )
                {
                    tokens.avancaPonteiro();
                    
                    if ( tokens.getTokenAtual() == "else" )
                    {
                        filho = noExpressao->inserirFilho("[else]");
                        tokens.avancaPonteiro();

                        if ( comandoSemRotulo(filho) ) return true;
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        tokens.retrocedePonteiro();
                        return true;
                    }
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    } 
    else if ( tokens.getTokenAtual() == "while" )
    {
        NoArvore *noExpressao = parent->inserirFilho("while");
        NoArvore *noCondition = noExpressao->inserirFilho("[condiction]");

        tokens.avancaPonteiro();

        this->mIsExpressao = true;
        this->mListaExpressao  = new std::list<std::string>;
        
        if ( expressao() )
        {
            this->mIsExpressao = false;
            noCondition->inserirFilho(this->mListaExpressao);

            tokens.avancaPonteiro();
            
            if ( tokens.getTokenAtual() == "do" )
            {
                NoArvore *filho = noExpressao->inserirFilho("[do]");
                
                tokens.avancaPonteiro();
                
                if ( comandoSemRotulo(filho) ) return true;
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    } 
    else if ( identificador() )
    {
        TToken temp = tokens.getTokenAtual();

        if ( tokens.getProxToken() == "(" )
        {
            NoArvore *callProc   = parent->inserirFilho("[CALL PROCEDURE|CALL FUNCTION]");
//            NoArvore *parametros = callProc->inserirFilho(tokens.getTokenAtual().token);

           
            this->mIsExpressao = true;
            this->mListaExpressao = new std::list<std::string>;
            
            this->mListaExpressao->push_back(tokens.getTokenAtual().token);
            this->mListaExpressao->push_back("(");

            tokens.avancaPonteiro();
            tokens.avancaPonteiro();

            if ( expressao() )
            {
                this->mIsExpressao = false;
                //parametros->inserirFilho(this->mListaExpressao);
                tokens.avancaPonteiro();

                if ( tokens.getTokenAtual() == ")" )
                {
                    this->mListaExpressao->push_back(")");
                    callProc->inserirFilho(this->mListaExpressao);
                    return true;
                }
                else if ( tokens.getTokenAtual() == "," )
                {
                    this->mListaExpressao->push_back(",");
                    bool continuar = true;
                    tokens.avancaPonteiro();

                    while (continuar)
                    {
                        this->mIsExpressao = true;
                        //this->mListaExpressao = new std::list<std::string>;
                        if ( expressao() )
                        {
                            this->mIsExpressao = false;
                            //parametros->inserirFilho(this->mListaExpressao);
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ")" )
                            {
                                this->mListaExpressao->push_back(")");
                                callProc->inserirFilho(this->mListaExpressao);
                                return true;
                            }
                            else if ( tokens.getTokenAtual() == "," )
                            {
                                this->mListaExpressao->push_back(",");
                                tokens.avancaPonteiro();
                            }
                            else return false;
                        }
                        else return false;
                    }//while (continuar)
                }//else if ( tokens.getProxToken() == "," )
                else return false;
                
            }//if ( expressao(parent) )
            else return false;
        }
        else if ( tokens.getProxToken() == ":=" )
        {
            NoArvore *atribuicao = parent->inserirFilho(":=");
            atribuicao->inserirFilho(tokens.getTokenAtual().token);

            tokens.avancaPonteiro();
            tokens.avancaPonteiro();

            this->mListaExpressao = new std::list<std::string>;
            this->mIsExpressao = true;

            if ( expressao() )
            {
                this->mIsExpressao = false;
                atribuicao->inserirFilho(this->mListaExpressao);
                return true;
            }
            else return false;
        }
        else
        {
            NoArvore *callProc   = parent->inserirFilho("[CALL PROCEDURE|CALL FUNCTION]");
            this->mListaExpressao = new std::list<std::string>;            
            this->mListaExpressao->push_back(tokens.getTokenAtual().token);
            callProc->inserirFilho(this->mListaExpressao);
            return true;
        }
    }
    else
    {
        return false;
    }
}

bool Sintatico::comando(NoArvore *parent)
{
    if ( numero() )
    {
        tokens.avancaPonteiro();
        if ( tokens.getTokenAtual() == ":" )
            tokens.avancaPonteiro();
        else
            return false;
    }

    if ( comandoSemRotulo(parent) )
        return true;
    else
        return false;
}

bool Sintatico::parametrosFormais(NoArvore *parent, IdentificadorProcFunc *pProcFunc)
{
    NoArvore *noParametros = parent->inserirFilho("[PARAMETROS]");
    
    if ( tokens.getTokenAtual() == "(" )
    {
        tokens.avancaPonteiro();

        bool proc = false;        
        bool continuar = true;
        std::list<IdentificadorParametro *> pilhaParametrosDeslocamento;
        std::list<IdentificadorParametro *> pilhaParametrosTipo;
        while (continuar)
        {
        
            bool isReferencia = false;
        
            if ( tokens.getTokenAtual() == "var" )
            {
                isReferencia = true;
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "function" )
            {
                tokens.avancaPonteiro();
            }
            else if ( tokens.getTokenAtual() == "procedure" )
            {
                proc = true;
                tokens.avancaPonteiro();
            }
            
            bool loopInterno = true;
            
            
            
            
            while (loopInterno)
            {
                if ( identificador() )
                {
                    noParametros->inserirFilho(tokens.getTokenAtual().token);

                    IdentificadorParametro *idParametro = new IdentificadorParametro(tokens.getTokenAtual().token,
                                                                                     1,
                                                                                     getNivel(),
                                                                                     this->procFunc.back(),
                                                                                     "",
                                                                                     0,
                                                                                     isReferencia);

                    mTabelaHash->inserir(idParametro);
                    pProcFunc->inserirParametro(idParametro);
                    pilhaParametrosTipo.push_back(idParametro);
                    pilhaParametrosDeslocamento.push_back(idParametro);

                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == "," )
                    {
                        tokens.avancaPonteiro();
                    }
                    else if ( tokens.getTokenAtual() == ";" && proc )
                    {
                        tokens.avancaPonteiro();
                        loopInterno = false;
                    }
                    else if ( tokens.getTokenAtual() == ":" )
                    {
                        loopInterno = false;
                        tokens.avancaPonteiro();

                        if ( tipo() )
                        {
                            // seta os tipos do parametros e os coloca na sua respectiva funcao/procedicmento
                            while(pilhaParametrosTipo.empty() == false)
                            {
                                idParametro = pilhaParametrosTipo.front();
                                idParametro->setTipo(tokens.getTokenAtual().token);
                                pilhaParametrosTipo.pop_front();
                            }
                        
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ";" )
                            {
                                tokens.avancaPonteiro();
                            }
                            else if ( tokens.getTokenAtual() == ")" )
                            {
                                int deslocamento = -3;
                                pProcFunc->setN(pilhaParametrosDeslocamento.size());
                                while(pilhaParametrosDeslocamento.empty() == false)
                                {                                
                                    idParametro = pilhaParametrosDeslocamento.back();
                                    idParametro->setDeslocamento(deslocamento--);
                                    pilhaParametrosDeslocamento.pop_back();
                                    pProcFunc->inserirParametro(idParametro);
                                }
                                pProcFunc->setDeslocamento(deslocamento);
                                
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else if ( tokens.getTokenAtual() == ")" && proc )
                    {
                        return true;
                    }
                    else return false;
                }
                else 
                {
                    return false;
                }
            }//while (loopInterno)
                        
        }//while (continuar)
    }
    else
    {
        return false;
    }
}

bool Sintatico::tipo()
{
    TToken temp;
    temp = tokens.getTokenAtual();

    if ( temp.isTipoVariavel() == true )
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Sintatico::bloco(NoArvore *parent)
{
    NoArvore *noVars     = parent->inserirFilho("[VARIAVEIS]");
    NoArvore *noFuncProc = parent->inserirFilho("[FUNCOES|PROCEDIMENTOS]");
    NoArvore *noCommands = parent->inserirFilho("[COMANDOS]");

    bool continuar = true;
    NoArvore *filho = NULL;
    while (continuar)
    {
        if ( tokens.getTokenAtual() == "var" )
        {
            int deslocamento = 0;

            tokens.avancaPonteiro();

            bool loopInterno = true;

            std::list<IdentificadorVariavel *> pilhaIdentificador;
            while ( loopInterno )
            {
                if ( identificador() )
                {
                    noVars->inserirFilho(tokens.getTokenAtual().token);
                    IdentificadorVariavel *id = new IdentificadorVariavel(tokens.getTokenAtual().token,
                                                                          0,
                                                                          this->getNivel(),
                                                                          this->procFunc.back(),
                                                                          "",
                                                                          deslocamento++);

                    mTabelaHash->inserir(id);
                    pilhaIdentificador.push_back(id);

                    tokens.avancaPonteiro();
                    
                    if ( tokens.getTokenAtual() == "," )
                    {
                        tokens.avancaPonteiro();
                    } 
                    else if ( tokens.getTokenAtual() == ":" )
                    {
                        tokens.avancaPonteiro();
                        if ( tipo() )
                        {
                            while (pilhaIdentificador.empty() == false)
                            {
                                id = pilhaIdentificador.back();
                                id->setTipo(tokens.getTokenAtual().token);
                                pilhaIdentificador.pop_back();
                                
                            }
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ";" )
                            {
                                tokens.avancaPonteiro();

                                if ( !identificador() ) loopInterno = false;
                            }
                            else return false;
                        }
                        else return false;
                    }
                    else return false;
                }
                else return false;
            }//while ( loopInterno )
        }
        else if ( tokens.getTokenAtual() == "procedure" )
        {
            this->incrementaNivel();
            filho = noFuncProc->inserirFilho("[PROCEDIMENTO]");


            tokens.avancaPonteiro();

            if ( identificador() )
            {
                filho->inserirFilho(tokens.getTokenAtual().token);


                                
                IdentificadorProcFunc *id = new IdentificadorProcFunc(tokens.getTokenAtual().token,
                                                                      2,
                                                                      this->getNivel(),
                                                                      this->procFunc.back(),
                                                                      0,
                                                                      0,
                                                                      "");
                
                mTabelaHash->inserir(id);
                procFunc.push_back(tokens.getTokenAtual().token);
                tokens.avancaPonteiro();
                
                if ( tokens.getTokenAtual() == ";" )
                {
                    tokens.avancaPonteiro();
                }
                else if ( parametrosFormais(filho, id) )
                {
                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == ";" )
                    {
                        tokens.avancaPonteiro();
                    }
                    else return false;
                }
                else return false;

                if ( bloco(filho) )
                {
                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == ";" )
                    {
                        tokens.avancaPonteiro();
                        procFunc.pop_back();
                        this->decrementaNivel();
                    }
                    else return false;
                }
                else return false;
            }
            else return false;
        }
        else if ( tokens.getTokenAtual() == "function" )
        {
            this->incrementaNivel();
            filho = noFuncProc->inserirFilho("[FUNCAO]");
            
            tokens.avancaPonteiro();
            
            if ( identificador() )
            {
                filho->inserirFilho(tokens.getTokenAtual().token);

                IdentificadorProcFunc *id = new IdentificadorProcFunc(tokens.getTokenAtual().token,
                                                                      3,
                                                                      this->getNivel(),
                                                                      this->procFunc.back(),
                                                                      0,
                                                                      0,
                                                                      "");
                mTabelaHash->inserir(id);
                procFunc.push_back(tokens.getTokenAtual().token);
                tokens.avancaPonteiro();

                if ( tokens.getTokenAtual() == ":" )
                {
                    tokens.avancaPonteiro();
                }
                else if ( parametrosFormais(filho, id) )
                {
                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == ":" )
                    {
                        tokens.avancaPonteiro();
                    }
                    else return false;
                }
                else return false;
                
                if ( tipo() )
                {
                    // seta o tipo de retorno da funcao
                    id->setRetorno(tokens.getTokenAtual().token);
                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == ";" )
                    {
                        tokens.avancaPonteiro();
                        if ( bloco(filho) )
                        {
                            tokens.avancaPonteiro();
                            if ( tokens.getTokenAtual() == ";" )
                            {
                                tokens.avancaPonteiro();
                                procFunc.pop_back();
                                this->decrementaNivel();
                            }
                            else return false;
                        }
                        else return false;
                    }
                    else return false;
                }
                else return false;
            }
            else return false;
        }
        else if ( tokens.getTokenAtual() == "begin" )
        {
            continuar = false;
            tokens.avancaPonteiro();
            
            bool loopInterno = true;
            while ( loopInterno )
            {
                if ( comando(noCommands) )
                {
                    tokens.avancaPonteiro();
                    if ( tokens.getTokenAtual() == ";" )
                    {
                        tokens.avancaPonteiro();
                    }
                    else if ( tokens.getTokenAtual() == "end" )
                    {
                        loopInterno = false;
                        return true;
                    }
                    else return false;
                }
                else return false;
            }
        }
        else
        {
            return false;
        }
    }//while (continuar)

    return true;
}

bool Sintatico::programa(Arvore *parent)
{
    if ( tokens.getTokenAtual() == "program" )
    {
        NoArvore *program = parent->inserirRaiz("program");
        procFunc.push_back("program");
        tokens.avancaPonteiro();

        if ( identificador() )
        {
            program->inserirFilho(tokens.getTokenAtual().token);
            tokens.avancaPonteiro();
            bool continuar = true;

            if ( tokens.getTokenAtual() == ";" )
            {
                tokens.avancaPonteiro();

                if ( bloco(program) )
                {
                    tokens.avancaPonteiro();

                    if ( tokens.getTokenAtual() == "." )
                    {
                        procFunc.pop_back();
                        return true;
                    }
                    else return false;
                }
                else return false;
            }
            else return false;
        }
        else return false;
    }
    else return false;
}
// fim de arquivo
